#include "timeout_exit.h"

int init_element(queue_element *ele)
{
    for(int i=0;i<CLIENT_NUM;++i)
    {
        ele->fd[i]=-1;
    }
    ele->num=0;
    ele->isempty=true;
}
void initQueue_cir(CircularQueue *queue) {
    queue->front = 0;
    queue->rear = 0;
    queue->time_site=0;
    memset(queue->fd_hash,-1,sizeof(queue->fd_hash));
    queue_element temp;
    init_element(&temp);
    for(int i=0;i<WAIT_TIME;++i)
    {
        enqueue_cir(queue,temp);
    }

}

int isEmpty_cir(CircularQueue *queue) {
    return queue->front == queue->rear;
}

int isFull_cir(CircularQueue *queue) {
    return (queue->rear + 1) % (WAIT_TIME+1) == queue->front;
}

int enqueue_cir(CircularQueue *queue, queue_element ele) {
    if (isFull_cir(queue)) {
        printf("Queue is full\n");
        return 0;
    }
    queue->element[queue->rear] = ele;
    queue->rear = (queue->rear + 1) % WAIT_TIME;
    return 0;
}

int dequeue_cir(CircularQueue *queue, queue_element *ele) {
    if (isEmpty_cir(queue)) {
        printf("Queue is empty\n");
        return 0;
    }
    *ele=queue->element[queue->front];
    queue->front = (queue->front + 1) % WAIT_TIME;
    return 1;
}

int init_queue_hash_cir(CircularQueue *queue)
{
    bzero(queue->fd_hash,sizeof(queue->fd_hash));
}

int addelement_fd_cir(CircularQueue *queue,int fd)
{
    int num=queue->element[queue->time_site].num;
    (queue->element[queue->time_site].num)++;
    del_ele_cir(queue,fd);
    queue->element[queue->time_site].fd[num]=fd;
    queue->fd_hash[fd]=queue->time_site;
    queue->element[queue->time_site].isempty=false;
    return 0;
}

int del_ele_cir(CircularQueue *queue,int fd)
{
    int site=queue->fd_hash[fd];
    if(site==-1)
    {
        return 0;
    }
    int i=0;
    for(i;i<queue->element[site].num;++i)
    {
        if(queue->element[site].fd[i]==fd)
        {
            queue->element[site].fd[i]=queue->element[site].fd[queue->element[site].num-1];
            queue->element[site].fd[queue->element[site].num-1]=-1;
            queue->element[site].num--;
            queue->fd_hash[fd]=-1;
            if(queue->element[site].num==0)
            {
                queue->element[site].isempty=true;
            }
        }
        else if(i==queue->element[site].num-1&&fd!=queue->element[site].fd[queue->element[site].num-1])
        {
            return -1;
        }
    }
    return 0;
}

int clear_ele_cir(CircularQueue *queue)
{
    int fd;
    for(int i=0;i<queue->element[queue->time_site].num;++i)
    {
        fd=queue->element[queue->time_site].fd[i];
        queue->fd_hash[fd]=-1;
        close(fd);
        if(fd!=-1)
        {
            printf("用户%d已被踢出\n",fd);
        }
        queue->element[queue->time_site].fd[i]=-1;
    }
    queue->element[queue->time_site].isempty=true;
    queue->element[queue->time_site].num=0;
}

int timeout_exit(int fd,time_t *pass_time,int *time_flag,CircularQueue * queue)
{
    time_t now=time(NULL);
    printf("%s\n",ctime(&now));
    if(fd==-1)
    {

        if(*time_flag==WAIT_TIME)
        {
            *pass_time=*pass_time-*time_flag;
        }
        ++(*time_flag);
        if(*time_flag==WAIT_TIME+1)
        {
            *time_flag=1;
        }
        queue->time_site=(queue->time_site+1)%WAIT_TIME;
        if(queue->element[queue->time_site].isempty==false)
        {
            clear_ele_cir(queue);
        }
    }
    else {
        if(*pass_time<*time_flag)
        {
            addelement_fd_cir(queue,fd);
        }
        else
        {
            queue->time_site=(queue->time_site+1)%WAIT_TIME;
            // printf("site=%d\n",queue->time_site);
            if(queue->element[queue->time_site].isempty==false)
            {
               // printf("用户%d已被踢出\n",fd);
                clear_ele_cir(queue);
            }
            addelement_fd_cir(queue,fd);
            if(*time_flag==WAIT_TIME)
            {
                *pass_time=*pass_time-*time_flag;
            }
            ++(*time_flag);
            if(*time_flag==WAIT_TIME+1)
            {
                *time_flag=1;
            }
        }

    }
    return 0;
}

